From c9023cadbfed9a4831287a366cc3367c7baa436c Mon Sep 17 00:00:00 2001 From: Arx Cruz Date: Thu, 4 Aug 2011 15:34:16 -0300 Subject: [PATCH] [filechooser] bgo#349502: Context menu option to copy selected files to the clipboard --- gtk/gtkfilechooserdefault.c | 126 ++++++++++++++++++++++++++++++++++++ gtk/gtkfilechooserprivate.h | 1 + 2 files changed, 127 insertions(+) diff --git a/gtk/gtkfilechooserdefault.c b/gtk/gtkfilechooserdefault.c index 15c00996f1..ae54d2ab51 100644 --- a/gtk/gtkfilechooserdefault.c +++ b/gtk/gtkfilechooserdefault.c @@ -86,6 +86,10 @@ #include #endif +/* Values for GtkSelection-related "info" fields */ +#define SELECTION_TEXT 0 +#define SELECTION_URI 1 + /* Profiling stuff */ #undef PROFILE_FILE_CHOOSER #ifdef PROFILE_FILE_CHOOSER @@ -96,6 +100,7 @@ #endif #define PROFILE_INDENT 4 + static int profile_indent; static void @@ -3787,6 +3792,7 @@ popup_menu_detach_cb (GtkWidget *attach_widget, impl->browse_files_popup_menu = NULL; impl->browse_files_popup_menu_add_shortcut_item = NULL; impl->browse_files_popup_menu_hidden_files_item = NULL; + impl->browse_files_popup_menu_copy_file_location_item = NULL; } /* Callback used when the "Add to Bookmarks" menu item is activated */ @@ -3797,6 +3803,97 @@ add_to_shortcuts_cb (GtkMenuItem *item, bookmarks_add_selected_folder (impl); } +/* callback used to set data to clipboard */ +static void +copy_file_get_cb (GtkClipboard *clipboard, + GtkSelectionData *selection_data, + guint info, + gpointer data) +{ + GSList *selected_files = data; + + if (selected_files) + { + gint num_files = g_slist_length (selected_files); + gchar **uris; + gint i; + GSList *l; + + uris = g_new (gchar *, num_files + 1); + uris[num_files] = NULL; /* null terminator */ + + i = 0; + + for (l = selected_files; l; l = l->next) + { + GFile *file = (GFile *) l->data; + + if (info == SELECTION_URI) + uris[i] = g_file_get_uri (file); + else /* if (info == SELECTION_TEXT) - let this be the fallback */ + uris[i] = g_file_get_parse_name (file); + + i++; + } + + if (info == SELECTION_URI) + gtk_selection_data_set_uris (selection_data, uris); + else /* if (info == SELECTION_TEXT) - let this be the fallback */ + { + char *str = g_strjoinv (" ", uris); + gtk_selection_data_set_text (selection_data, str, -1); + g_free (str); + } + + g_strfreev (uris); + } +} + +/* callback used to clear the clipboard data */ +static void +copy_file_clear_cb (GtkClipboard *clipboard, + gpointer data) +{ + GSList *selected_files = data; + + g_slist_foreach (selected_files, (GFunc) g_object_unref, NULL); + g_slist_free (selected_files); +} + +/* Callback used when the "Copy file's location" menu item is activated */ +static void +copy_file_location_cb (GtkMenuItem *item, + GtkFileChooserDefault *impl) +{ + GSList *selected_files = NULL; + + selected_files = search_get_selected_files (impl); + + if (selected_files) + { + GtkClipboard *clipboard; + GtkTargetList *target_list; + GtkTargetEntry *targets; + int n_targets; + + clipboard = gtk_widget_get_clipboard (GTK_WIDGET (impl), GDK_SELECTION_CLIPBOARD); + + target_list = gtk_target_list_new (NULL, 0); + gtk_target_list_add_text_targets (target_list, SELECTION_TEXT); + gtk_target_list_add_uri_targets (target_list, SELECTION_URI); + + targets = gtk_target_table_new_from_list (target_list, &n_targets); + gtk_target_list_unref (target_list); + + gtk_clipboard_set_with_data (clipboard, targets, n_targets, + copy_file_get_cb, + copy_file_clear_cb, + selected_files); + + gtk_target_table_free (targets, n_targets); + } +} + /* Callback used when the "Show Hidden Files" menu item is toggled */ static void show_hidden_toggled_cb (GtkCheckMenuItem *item, @@ -3984,6 +4081,24 @@ file_list_drag_motion_cb (GtkWidget *widget, return TRUE; } +/* Sensitizes the "Copy file's location" context menu item if there is actually + * a selection active. + */ +static void +check_copy_file_location_sensitivity (GtkFileChooserDefault *impl) +{ + GtkTreeSelection *selection; + gboolean active; + + selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (impl->browse_files_tree_view)); + if (gtk_tree_selection_count_selected_rows (selection) == 0) + active = FALSE; + else + active = TRUE; + + gtk_widget_set_sensitive (impl->browse_files_popup_menu_copy_file_location_item, active); +} + /* Constructs the popup menu for the file list if needed */ static void file_list_build_popup_menu (GtkFileChooserDefault *impl) @@ -3998,6 +4113,15 @@ file_list_build_popup_menu (GtkFileChooserDefault *impl) impl->browse_files_tree_view, popup_menu_detach_cb); + item = gtk_image_menu_item_new_with_mnemonic (_("_Copy file's location")); + impl->browse_files_popup_menu_copy_file_location_item = item; + gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item), + gtk_image_new_from_stock (GTK_STOCK_COPY, GTK_ICON_SIZE_MENU)); + g_signal_connect (item, "activate", + G_CALLBACK (copy_file_location_cb), impl); + gtk_widget_show (item); + gtk_menu_shell_append (GTK_MENU_SHELL (impl->browse_files_popup_menu), item); + item = gtk_image_menu_item_new_with_mnemonic (_("_Add to Bookmarks")); impl->browse_files_popup_menu_add_shortcut_item = item; gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item), @@ -4026,6 +4150,7 @@ file_list_build_popup_menu (GtkFileChooserDefault *impl) gtk_menu_shell_append (GTK_MENU_SHELL (impl->browse_files_popup_menu), item); bookmarks_check_add_sensitivity (impl); + check_copy_file_location_sensitivity (impl); } /* Updates the popup menu for the file list, creating it if necessary */ @@ -9969,6 +10094,7 @@ list_selection_changed (GtkTreeSelection *selection, check_preview_change (impl); bookmarks_check_add_sensitivity (impl); + check_copy_file_location_sensitivity (impl); g_signal_emit_by_name (impl, "selection-changed", 0); } diff --git a/gtk/gtkfilechooserprivate.h b/gtk/gtkfilechooserprivate.h index dd4bccb97b..81fc3b25da 100644 --- a/gtk/gtkfilechooserprivate.h +++ b/gtk/gtkfilechooserprivate.h @@ -180,6 +180,7 @@ struct _GtkFileChooserDefault GtkWidget *browse_files_popup_menu_add_shortcut_item; GtkWidget *browse_files_popup_menu_hidden_files_item; GtkWidget *browse_files_popup_menu_size_column_item; + GtkWidget *browse_files_popup_menu_copy_file_location_item; GtkWidget *browse_new_folder_button; GtkWidget *browse_path_bar_hbox; GtkSizeGroup *browse_path_bar_size_group; -- 2.30.2